package gugga.tasks
{
	import flash.events.EventDispatcher;
	import gugga.tasks.events.TaskEvent;

	[Event(name="start", type="TaskEvent")]
	[Event(name="interrupted", type="TaskEvent")]
	[Event(name="completed", type="TaskEvent")]
	
	/**
	 * <code>ExecuteMethodTask</code> is a task that invokes a method and right after the 
	 * invokation it dispatches the <b><i>completed</i></b>-event.
	 * <p>
	 * An <code>ExecuteMethodTask</code> object is initialized with the 
	 * <code>static</code> method <code>create()</code> which expects the following parameters:
	 * <ul>
	 * 	<li>a method</li>
	 * 	<li>an array of arguments for the specified method</li>
	 * 	<li>an optional context object in which the specified method is evaluated</li>
	 * </ul>
	 */
	public class ExecuteMethodTask extends EventDispatcher implements ITask 
	{
		private var mIsRunning:Boolean;
		
		private var mMethodScope:*;
		private var mMethodFunction:Function;
		
		private var mMethodArguments : Array;
		public function get MethodArguments() : Array { return mMethodArguments; }
		public function set MethodArguments(aValue : Array) : void { mMethodArguments = aValue; }
		
		public function ExecuteMethodTask(aMethodFunction:Function, aMethodArguments:Array, aMethodScope:* = null) 
		{
			mIsRunning = false;
			mMethodScope = aMethodScope;
			mMethodFunction = aMethodFunction;
			mMethodArguments = aMethodArguments;
		}
		
		public function isRunning() : Boolean 
		{
			return mIsRunning;
		}
		
		public function start() : void 
		{
			mIsRunning = true;
			dispatchEvent(new TaskEvent(TaskEvent.START));
			mMethodFunction.apply(mMethodScope, mMethodArguments);
			mIsRunning = false;
			dispatchEvent(new TaskEvent(TaskEvent.COMPLETED));
		}
		
		public function isImmediatelyInterruptable() : Boolean
		{
			return true;
		}
		
		public function interrupt() : void 
		{
			mIsRunning = false;
			dispatchEvent(new TaskEvent(TaskEvent.INTERRUPTED));
		}
		
		public static function create(aMethodFunction:Function, aMethodArguments:Array, aMethodScope:* = null) : ExecuteMethodTask
		{
			var executeMethodTask : ExecuteMethodTask = new ExecuteMethodTask(aMethodFunction, aMethodArguments, aMethodScope);
			return executeMethodTask;
		}
	}
}